#include <iostream>
#include <windows.h>
#include <dbghelp.h>
#include <psapi.h>

extern "C" __declspec(dllexport) int InitSym() {
    std::cout << "=====================" << std::endl;
    DWORD cbNeeded;
    HMODULE hModules[1024];
    HANDLE hProcess = GetCurrentProcess();
    SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
    if (!SymInitialize(hProcess, NULL, TRUE)) {
        std::cerr << "Failed to initialize symbols." << std::endl;
        CloseHandle(hProcess);
        return 1;
    }
    if (EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded)) {
        for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
            MODULEINFO moduleInfo;
            if (GetModuleInformation(hProcess, hModules[i], &moduleInfo, sizeof(moduleInfo))) {
                char moduleName[MAX_PATH];
                GetModuleFileNameExA(hProcess, hModules[i], moduleName, MAX_PATH);
                SymLoadModule64(hProcess, NULL, moduleName, NULL, (DWORD64)moduleInfo.lpBaseOfDll, moduleInfo.SizeOfImage);
                std::cout << moduleInfo.lpBaseOfDll <<" " << moduleInfo.EntryPoint <<" " << moduleName << std::endl;
                DWORD64 dw64ModAddress = SymLoadModuleEx(hProcess,NULL,moduleName,NULL,0,0,NULL,0);
                SymEnumSymbols(hProcess, dw64ModAddress, NULL,  [](PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext)->BOOL{
                    printf("%08X\t%4u\t%s\n", pSymInfo->Address, SymbolSize, pSymInfo->Name);
                    // if (pSymInfo->Tag == SYMFLAG_FUNCTION) {
                    //     std::cout << pSymInfo->Address << " " << pSymInfo->Name << std::endl;
                    // }
                    return TRUE;
                }, NULL);
                SymUnloadModule64(hProcess, dw64ModAddress);
            }
        }
    }
    SymCleanup(hProcess);
    CloseHandle(hProcess);

    return 0;
}

int main(int args,char** argv) {
    InitSym();
}